package com.example.videoconverter;

import org.bytedeco.javacv.*;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 视频处理工具类
 * 提供视频帧抓取、图片序列转视频等实用功能
 */
public class VideoUtils {
    private static final Logger logger = LoggerFactory.getLogger(VideoUtils.class);
    
    /**
     * 从视频中提取指定帧并保存为图片
     * 
     * @param videoPath   视频文件路径
     * @param outputDir   输出图片目录
     * @param frameNumbers 要提取的帧号列表（从0开始）
     * @return 成功提取的帧数
     * @throws Exception 处理过程中的异常
     */
    public static int extractFrames(String videoPath, String outputDir, List<Integer> frameNumbers) throws Exception {
        File outputDirectory = new File(outputDir);
        if (!outputDirectory.exists()) {
            outputDirectory.mkdirs();
        }
        
        FFmpegFrameGrabber grabber = null;
        Java2DFrameConverter converter = new Java2DFrameConverter();
        int extractedCount = 0;
        
        try {
            grabber = new FFmpegFrameGrabber(videoPath);
            grabber.start();
            
            logger.info("开始从视频 {} 提取 {} 帧", videoPath, frameNumbers.size());
            
            for (int frameNumber : frameNumbers) {
                try {
                    // 跳转到指定帧
                    grabber.setFrameNumber(frameNumber);
                    Frame frame = grabber.grabImage();
                    
                    if (frame != null) {
                        // 转换为BufferedImage并保存
                        String outputPath = String.format("%s/frame_%06d.png", outputDir, frameNumber);
                        
                        // 使用OpenCV保存图片以获得更好的质量
                        OpenCVFrameConverter.ToMat matConverter = new OpenCVFrameConverter.ToMat();
                        Mat mat = matConverter.convert(frame);
                        opencv_imgcodecs.imwrite(outputPath, mat);
                        
                        extractedCount++;
                        logger.debug("提取帧 {} 保存到 {}", frameNumber, outputPath);
                    }
                } catch (Exception e) {
                    logger.warn("提取帧 {} 失败: {}", frameNumber, e.getMessage());
                }
            }
            
            logger.info("帧提取完成，成功提取 {} 帧", extractedCount);
            
        } finally {
            if (grabber != null) {
                grabber.stop();
                grabber.release();
            }
        }
        
        return extractedCount;
    }
    
    /**
     * 从视频中均匀提取指定数量的帧
     * 
     * @param videoPath  视频文件路径
     * @param outputDir  输出图片目录
     * @param frameCount 要提取的帧数
     * @return 成功提取的帧数
     * @throws Exception 处理过程中的异常
     */
    public static int extractFramesEvenly(String videoPath, String outputDir, int frameCount) throws Exception {
        FFmpegFrameGrabber grabber = null;
        
        try {
            grabber = new FFmpegFrameGrabber(videoPath);
            grabber.start();
            
            int totalFrames = grabber.getLengthInFrames();
            if (totalFrames <= 0) {
                throw new IllegalArgumentException("无法获取视频总帧数");
            }
            
            // 计算帧间隔
            List<Integer> frameNumbers = new ArrayList<>();
            if (frameCount >= totalFrames) {
                // 如果要提取的帧数大于等于总帧数，提取所有帧
                for (int i = 0; i < totalFrames; i++) {
                    frameNumbers.add(i);
                }
            } else {
                // 均匀分布提取帧
                double interval = (double) totalFrames / frameCount;
                for (int i = 0; i < frameCount; i++) {
                    int frameNumber = (int) Math.round(i * interval);
                    frameNumbers.add(Math.min(frameNumber, totalFrames - 1));
                }
            }
            
            grabber.stop();
            grabber.release();
            
            return extractFrames(videoPath, outputDir, frameNumbers);
            
        } finally {
            if (grabber != null && grabber.getFormatContext() != null) {
                grabber.stop();
                grabber.release();
            }
        }
    }
    
    /**
     * 将图片序列转换为视频
     * 
     * @param imageDir   图片目录
     * @param outputPath 输出视频路径
     * @param frameRate  帧率
     * @param imagePattern 图片文件名模式（如"frame_%06d.png"）
     * @throws Exception 处理过程中的异常
     */
    public static void createVideoFromImages(String imageDir, String outputPath, double frameRate, String imagePattern) throws Exception {
        File imgDir = new File(imageDir);
        if (!imgDir.exists() || !imgDir.isDirectory()) {
            throw new IllegalArgumentException("图片目录不存在: " + imageDir);
        }
        
        // 获取第一张图片来确定视频尺寸
        File[] imageFiles = imgDir.listFiles((dir, name) -> 
            name.toLowerCase().endsWith(".png") || 
            name.toLowerCase().endsWith(".jpg") || 
            name.toLowerCase().endsWith(".jpeg")
        );
        
        if (imageFiles == null || imageFiles.length == 0) {
            throw new IllegalArgumentException("图片目录中没有找到图片文件");
        }
        
        FFmpegFrameGrabber sampleGrabber = null;
        FFmpegFrameRecorder recorder = null;
        
        try {
            // 读取第一张图片获取尺寸
            sampleGrabber = new FFmpegFrameGrabber(imageFiles[0].getAbsolutePath());
            sampleGrabber.start();
            
            int width = sampleGrabber.getImageWidth();
            int height = sampleGrabber.getImageHeight();
            
            sampleGrabber.stop();
            sampleGrabber.release();
            
            // 创建视频录制器
            recorder = new FFmpegFrameRecorder(outputPath, width, height);
            recorder.setVideoCodec(org.bytedeco.ffmpeg.global.avcodec.AV_CODEC_ID_H264);
            recorder.setFormat("mp4");
            recorder.setFrameRate(frameRate);
            recorder.setVideoQuality(23);
            
            recorder.start();
            
            logger.info("开始从 {} 张图片创建视频", imageFiles.length);
            
            // 按文件名排序
            java.util.Arrays.sort(imageFiles, (a, b) -> a.getName().compareTo(b.getName()));
            
            // 逐个读取图片并录制
            for (File imageFile : imageFiles) {
                FFmpegFrameGrabber imageGrabber = new FFmpegFrameGrabber(imageFile.getAbsolutePath());
                imageGrabber.start();
                
                Frame frame = imageGrabber.grabImage();
                if (frame != null) {
                    recorder.record(frame);
                }
                
                imageGrabber.stop();
                imageGrabber.release();
            }
            
            logger.info("视频创建完成: {}", outputPath);
            
        } finally {
            if (recorder != null) {
                recorder.stop();
                recorder.release();
            }
        }
    }
    
    /**
     * 验证视频文件是否有效
     * 
     * @param videoPath 视频文件路径
     * @return 是否为有效的视频文件
     */
    public static boolean isValidVideo(String videoPath) {
        FFmpegFrameGrabber grabber = null;
        try {
            File videoFile = new File(videoPath);
            if (!videoFile.exists() || videoFile.length() == 0) {
                return false;
            }
            
            grabber = new FFmpegFrameGrabber(videoPath);
            grabber.start();
            
            // 尝试读取第一帧
            Frame frame = grabber.grabImage();
            boolean isValid = frame != null && grabber.getImageWidth() > 0 && grabber.getImageHeight() > 0;
            
            return isValid;
            
        } catch (Exception e) {
            logger.debug("视频文件验证失败: {}", e.getMessage());
            return false;
        } finally {
            if (grabber != null) {
                try {
                    grabber.stop();
                    grabber.release();
                } catch (Exception e) {
                    // 忽略关闭时的异常
                }
            }
        }
    }
    
    /**
     * 获取支持的视频格式列表
     * 
     * @return 支持的视频格式扩展名列表
     */
    public static List<String> getSupportedVideoFormats() {
        List<String> formats = new ArrayList<>();
        formats.add("avi");
        formats.add("mp4");
        formats.add("mov");
        formats.add("mkv");
        formats.add("flv");
        formats.add("wmv");
        formats.add("webm");
        return formats;
    }
}